home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.002 / stk-3 / STk-3.1 / Tk / win / tkWinPointer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-17  |  20.0 KB  |  849 lines

  1. /* 
  2.  * tkWinPointer.c --
  3.  *
  4.  *    Windows specific mouse tracking code.
  5.  *
  6.  * Copyright (c) 1995 Sun Microsystems, Inc.
  7.  *
  8.  * See the file "license.terms" for information on usage and redistribution
  9.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  10.  *
  11.  * SCCS: @(#) tkWinPointer.c 1.14 96/02/15 18:56:05
  12.  */
  13.  
  14. #include "tkWinInt.h"
  15.  
  16. /*
  17.  * Check for enter/leave events every MOUSE_TIMER_INTERVAL milliseconds.
  18.  */
  19.  
  20. #define MOUSE_TIMER_INTERVAL 250
  21.  
  22. /*
  23.  * Mask that selects any of the state bits corresponding to buttons,
  24.  * plus masks that select individual buttons' bits:
  25.  */
  26.  
  27. #define ALL_BUTTONS \
  28.     (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
  29. static unsigned int buttonStates[] = {
  30.     Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
  31. };
  32.  
  33. /*
  34.  * Declarations of static variables used in the grab module.
  35.  */
  36.  
  37. static int captured;        /* 1 if mouse events outside of Tk windows
  38.                  * will be reported, else 0. */
  39. static TkWindow *grabWinPtr;    /* Window that defines the top of the grab
  40.                  * tree in a global grab. */
  41. static TkWindow *keyboardWinPtr;/* Current keyboard grab window. */
  42. static TkWindow *restrictWinPtr;
  43.                 /* Window to which all mouse
  44.                    events will be reported. */
  45.  
  46. /*
  47.  * Declarations of static variables used in mouse position tracking.
  48.  */
  49.  
  50. static POINT lastMousePos;    /* Last known mouse position. */
  51. static HWND lastMouseWindow;    /* Last known mouse window. */
  52. static TkWindow *lastMouseWinPtr;
  53.                 /* Last window mouse was seen in.  Used to
  54.                  * detect Enter/Leave events. */
  55. static Tcl_TimerToken mouseTimer;
  56.                 /* Handle to the latest mouse timer. */
  57. static int mouseTimerSet;    /* Non-zero if the mouse timer is active. */
  58.  
  59. /*
  60.  * Forward declarations of procedures used in this file.
  61.  */
  62.  
  63. static void        InitializeCrossingEvent _ANSI_ARGS_((
  64.                     XEvent* eventPtr, TkWindow *winPtr,
  65.                 long x, long y));
  66. static void        MouseTimerProc _ANSI_ARGS_((ClientData clientData));
  67. static int        UpdateMousePosition _ANSI_ARGS_((HWND hwnd,
  68.                 TkWindow *winPtr, long x, long y));
  69.  
  70. /*
  71.  *----------------------------------------------------------------------
  72.  *
  73.  * TkWinPointerInit --
  74.  *
  75.  *    Initialize the mouse pointer module.
  76.  *
  77.  * Results:
  78.  *    None.
  79.  *
  80.  * Side effects:
  81.  *    Initializes various static variables.
  82.  *
  83.  *----------------------------------------------------------------------
  84.  */
  85.  
  86. void
  87. TkWinPointerInit()
  88. {
  89.     captured = 0;
  90.     grabWinPtr = NULL;
  91.     keyboardWinPtr = NULL;
  92.     restrictWinPtr = NULL;
  93.  
  94.     mouseTimerSet = 0;
  95.     GetCursorPos(&lastMousePos);
  96.     lastMouseWindow = WindowFromPoint(lastMousePos);
  97.     lastMouseWinPtr = NULL;
  98. }
  99.  
  100. /*
  101.  *----------------------------------------------------------------------
  102.  *
  103.  * TkWinPointerDeadWindow --
  104.  *
  105.  *    Clean up pointer module state when a window is destroyed.
  106.  *
  107.  * Results:
  108.  *    None.
  109.  *
  110.  * Side effects:
  111.  *    May change the grab module settings.
  112.  *
  113.  *----------------------------------------------------------------------
  114.  */
  115.  
  116. void
  117. TkWinPointerDeadWindow(winPtr)
  118.     TkWindow *winPtr;
  119. {
  120.     if (winPtr == lastMouseWinPtr) {
  121.     lastMouseWinPtr = NULL;
  122.     }
  123.     if (winPtr == grabWinPtr) {
  124.     grabWinPtr = NULL;
  125.     }
  126.     if (winPtr == restrictWinPtr) {
  127.     restrictWinPtr = NULL;
  128.     }
  129.     if (!(restrictWinPtr || grabWinPtr)) {
  130.     captured = 0;
  131.     ReleaseCapture();
  132.     }
  133. }
  134.  
  135. /*
  136.  *----------------------------------------------------------------------
  137.  *
  138.  * TkWinPointerEvent --
  139.  *
  140.  *    This procedure is called for each pointer-related event,
  141.  *    before the event is queued.  It simulates X style automatic
  142.  *    grabs so that button release events are not lost.  It also
  143.  *    updates the pointer position so enter/leave events will be
  144.  *    correctly generated.
  145.  *
  146.  * Results:
  147.  *    Returns 0 if the event should be discarded.
  148.  *
  149.  * Side effects:
  150.  *    Changes the current mouse capture window. 
  151.  *
  152.  *----------------------------------------------------------------------
  153.  */
  154.  
  155. void
  156. TkWinPointerEvent(eventPtr, winPtr)
  157.     XEvent *eventPtr;        /* Event to process */
  158.     TkWindow *winPtr;        /* Window to which event was reported. */
  159. {
  160.     POINT pos;
  161.     HWND hwnd;
  162.     TkWinDrawable *twdPtr;
  163.  
  164.     /*
  165.      * If the mouse is captured, Windows will report all pointer
  166.      * events to the capture window.  So, we need to determine which
  167.      * window the mouse is really over and change the event.  Note
  168.      * that the computed hwnd may point to a window not owned by Tk,
  169.      * or a toplevel decorative frame, so winPtr can be NULL.
  170.      */
  171.  
  172.     if (captured) {
  173.     pos.x = eventPtr->xmotion.x_root;
  174.     pos.y = eventPtr->xmotion.y_root;
  175.     hwnd = WindowFromPoint(pos);
  176.     twdPtr = TkWinGetDrawableFromHandle(hwnd);
  177.     if (twdPtr && (twdPtr->type == TWD_WINDOW)) {
  178.         winPtr = TkWinGetWinPtr(twdPtr);
  179.     } else {
  180.         winPtr = NULL;
  181.     }
  182.     } else {
  183.     hwnd = TkWinGetHWND(Tk_WindowId(winPtr));
  184.     }
  185.  
  186.     switch (eventPtr->type) {
  187.     case MotionNotify: 
  188.  
  189.         /*
  190.          * If updating the mouse position caused an enter or leave
  191.          * event to be generated, we discard the motion event.
  192.          */
  193.  
  194.         if (UpdateMousePosition(hwnd, winPtr, eventPtr->xmotion.x_root,
  195.             eventPtr->xmotion.y_root)) {
  196.         return;
  197.         }
  198.         break;
  199.  
  200.     case ButtonPress:
  201.  
  202.         /*
  203.          * Set mouse capture and the restrict window if we are
  204.          * currently unrestricted.  However, If this is not the
  205.          * first button pressed and we are already grabbed, do not
  206.          * change anything.
  207.          */
  208.  
  209.         if (!restrictWinPtr) {
  210.         if (!grabWinPtr) {
  211.             /*
  212.              * Mouse was ungrabbed, so set a button grab.
  213.              */
  214.  
  215.             restrictWinPtr = winPtr;
  216.             captured = 1;
  217.             SetCapture(hwnd);
  218.         } else if ((eventPtr->xmotion.state & ALL_BUTTONS) == 0) {
  219.  
  220.             /*
  221.              * Mouse was grabbed, but not in a button grab.
  222.              * Make sure the new restrict window is inside the
  223.              * current grab tree.
  224.              */
  225.  
  226.             if (TkPositionInTree(winPtr, grabWinPtr)
  227.                 == TK_GRAB_IN_TREE) {
  228.             restrictWinPtr = winPtr;
  229.             } else {
  230.             restrictWinPtr = grabWinPtr;
  231.             }
  232.             captured = 1;
  233.             SetCapture(TkWinGetHWND(Tk_WindowId(restrictWinPtr)));
  234.         }
  235.         }
  236.         break;
  237.  
  238.     case ButtonRelease:
  239.  
  240.         /*
  241.          * Release the mouse capture when the last button is
  242.          * released and we aren't in a global grab.
  243.          */
  244.             
  245.         if ((eventPtr->xbutton.state & ALL_BUTTONS)
  246.             == buttonStates[eventPtr->xbutton.button - Button1]) {
  247.         if (!grabWinPtr) {
  248.             captured = 0;
  249.             ReleaseCapture();
  250.         }
  251.  
  252.         /*
  253.          * If we are releasing a restrict window, then we need
  254.          * to send the button event followed by mouse motion from
  255.          * the restrict window the the current mouse position.
  256.          */
  257.  
  258.         if (restrictWinPtr) {
  259.             if (Tk_WindowId(restrictWinPtr) != eventPtr->xany.window) {
  260.             TkChangeEventWindow(eventPtr, restrictWinPtr);
  261.             }
  262.             Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);
  263.             lastMouseWinPtr = restrictWinPtr;
  264.             restrictWinPtr = NULL;
  265.             UpdateMousePosition(hwnd, winPtr, eventPtr->xmotion.x_root,
  266.                 eventPtr->xmotion.y_root);
  267.             return;
  268.         }
  269.         }
  270.         break;
  271.     }
  272.  
  273.     /*
  274.      * If a restrict window is set, make sure the pointer event is reported
  275.      * relative to that window.  Otherwise, if a global grab is in effect
  276.      * then events outside of window managed by Tk should be reported to the
  277.      * grab window.
  278.      */
  279.  
  280.     if (restrictWinPtr) {
  281.     winPtr = restrictWinPtr;
  282.     } else if (grabWinPtr && !winPtr) {
  283.     winPtr = grabWinPtr;
  284.     }
  285.  
  286.     /*
  287.      * If the target window has changed, update the coordinates in the event.
  288.      */
  289.  
  290.     if (winPtr && Tk_WindowId(winPtr) != eventPtr->xany.window) {
  291.     TkChangeEventWindow(eventPtr, winPtr);
  292.     }
  293.     Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);
  294. }
  295.  
  296. /*
  297.  *----------------------------------------------------------------------
  298.  *
  299.  * XGrabPointer --
  300.  *
  301.  *    Capture the mouse so event are reported outside of toplevels.
  302.  *    Note that this is a very limited implementation that only
  303.  *    supports GrabModeAsync and owner_events True.
  304.  *
  305.  * Results:
  306.  *    Always returns GrabSuccess.
  307.  *
  308.  * Side effects:
  309.  *    Turns on mouse capture, sets the global grab pointer, and
  310.  *    clears any window restrictions.
  311.  *
  312.  *----------------------------------------------------------------------
  313.  */
  314.  
  315. int
  316. XGrabPointer(display, grab_window, owner_events, event_mask, pointer_mode,
  317.     keyboard_mode, confine_to, cursor, time)
  318.     Display* display;
  319.     Window grab_window;
  320.     Bool owner_events;
  321.     unsigned int event_mask;
  322.     int pointer_mode;
  323.     int keyboard_mode;
  324.     Window confine_to;
  325.     Cursor cursor;
  326.     Time time;
  327. {
  328.     HWND hwnd = TkWinGetHWND(grab_window);
  329.     grabWinPtr = TkWinGetWinPtr(grab_window);
  330.     captured = 1;
  331.     restrictWinPtr = NULL;
  332.     SetCapture(hwnd);
  333.     if (TkPositionInTree(lastMouseWinPtr, grabWinPtr) == TK_GRAB_IN_TREE) {
  334.     TkWinUpdateCursor(lastMouseWinPtr);
  335.     } else {
  336.     TkWinUpdateCursor(grabWinPtr);
  337.     }
  338.     return GrabSuccess;
  339. }
  340.  
  341. /*
  342.  *----------------------------------------------------------------------
  343.  *
  344.  * XUngrabPointer --
  345.  *
  346.  *    Release the current grab.
  347.  *
  348.  * Results:
  349.  *    None.
  350.  *
  351.  * Side effects:
  352.  *    Releases the mouse capture.
  353.  *
  354.  *----------------------------------------------------------------------
  355.  */
  356.  
  357. void
  358. XUngrabPointer(display, time)
  359.     Display* display;
  360.     Time time;
  361. {
  362.     captured = 0;
  363.     grabWinPtr = NULL;
  364.     restrictWinPtr = NULL;
  365.     ReleaseCapture();
  366.     TkWinUpdateCursor(lastMouseWinPtr);
  367. }
  368.  
  369. /*
  370.  *----------------------------------------------------------------------
  371.  *
  372.  * XGrabKeyboard --
  373.  *
  374.  *    Simulates a keyboard grab by setting the focus.
  375.  *
  376.  * Results:
  377.  *    Always returns GrabSuccess.
  378.  *
  379.  * Side effects:
  380.  *    Sets the keyboard focus to the specified window.
  381.  *
  382.  *----------------------------------------------------------------------
  383.  */
  384.  
  385. int
  386. XGrabKeyboard(display, grab_window, owner_events, pointer_mode,
  387.     keyboard_mode, time)
  388.     Display* display;
  389.     Window grab_window;
  390.     Bool owner_events;
  391.     int pointer_mode;
  392.     int keyboard_mode;
  393.     Time time;
  394. {
  395.     keyboardWinPtr = TkWinGetWinPtr(grab_window);
  396.     return GrabSuccess;
  397. }
  398.  
  399. /*
  400.  *----------------------------------------------------------------------
  401.  *
  402.  * XUngrabKeyboard --
  403.  *
  404.  *    Releases the simulated keyboard grab.
  405.  *
  406.  * Results:
  407.  *    None.
  408.  *
  409.  * Side effects:
  410.  *    Sets the keyboard focus back to the value before the grab.
  411.  *
  412.  *----------------------------------------------------------------------
  413.  */
  414.  
  415. void
  416. XUngrabKeyboard(display, time)
  417.     Display* display;
  418.     Time time;
  419. {
  420.     keyboardWinPtr = NULL;
  421. }
  422.  
  423. /*
  424.  *----------------------------------------------------------------------
  425.  *
  426.  * InitializeCrossingEvent --
  427.  *
  428.  *    Initializes the common fields for enter/leave events.
  429.  *
  430.  * Results:
  431.  *    None.
  432.  *
  433.  * Side effects:
  434.  *    Fills in the specified event structure.
  435.  *
  436.  *----------------------------------------------------------------------
  437.  */
  438.  
  439. static void
  440. InitializeCrossingEvent(eventPtr, winPtr, x, y)
  441.     XEvent* eventPtr;        /* Event structure to initialize. */
  442.     TkWindow *winPtr;        /* Window to make event relative to. */
  443.     long x, y;            /* Root coords of event. */
  444. {
  445.     eventPtr->xcrossing.serial = LastKnownRequestProcessed(winPtr->display);
  446.     eventPtr->xcrossing.send_event = 0;
  447.     eventPtr->xcrossing.display = winPtr->display;
  448.     eventPtr->xcrossing.root = RootWindow(winPtr->display, winPtr->screenNum);
  449.     eventPtr->xcrossing.time = TkCurrentTime(winPtr->dispPtr);
  450.     eventPtr->xcrossing.x_root = x;
  451.     eventPtr->xcrossing.y_root = y;
  452.     eventPtr->xcrossing.state = TkWinGetModifierState(WM_MOUSEMOVE, 0, 0);
  453.     eventPtr->xcrossing.mode = NotifyNormal;
  454.     eventPtr->xcrossing.focus = False;
  455. }
  456.  
  457. /*
  458.  *----------------------------------------------------------------------
  459.  *
  460.  * UpdateMousePosition --
  461.  *
  462.  *    Update the current mouse window and position, and generate
  463.  *    any enter/leave events that are needed.  Will schedule a
  464.  *    timer to check the mouse position if the pointer is still
  465.  *    inside a Tk window.
  466.  *
  467.  * Results:
  468.  *    Returns 1 if enter/leave events were generated.
  469.  *
  470.  * Side effects:
  471.  *    May generate enter/leave events and schedule a timer.
  472.  *
  473.  *----------------------------------------------------------------------
  474.  */
  475.  
  476. int
  477. UpdateMousePosition(hwnd, winPtr, x, y)
  478.     HWND hwnd;            /* current mouse window */
  479.     TkWindow *winPtr;        /* current Tk window (or NULL)  */
  480.     long x;            /* current mouse position in */
  481.     long y;            /* root coordinates */
  482. {
  483.     int crossed = 0;        /* 1 if mouse crossed a window boundary */
  484.     TkWindow *cursorWinPtr;
  485.  
  486.     if (winPtr != lastMouseWinPtr) {
  487.     if (restrictWinPtr) {
  488.         int newPos, oldPos;
  489.  
  490.         newPos = TkPositionInTree(winPtr, restrictWinPtr);
  491.         oldPos = TkPositionInTree(lastMouseWinPtr, restrictWinPtr);
  492.  
  493.         /*
  494.          * Check if the mouse crossed into or out of the restrict
  495.          * window.  If so, we need to generate an Enter or Leave event.
  496.          */
  497.  
  498.         if ((newPos != oldPos) && ((newPos == TK_GRAB_IN_TREE)
  499.             || (oldPos == TK_GRAB_IN_TREE))) {
  500.         XEvent event;
  501.  
  502.         InitializeCrossingEvent(&event, restrictWinPtr, x, y);
  503.         if (newPos == TK_GRAB_IN_TREE) {
  504.             event.type = EnterNotify;
  505.         } else {
  506.             event.type = LeaveNotify;
  507.         }
  508.         if ((oldPos == TK_GRAB_ANCESTOR)
  509.             || (newPos == TK_GRAB_ANCESTOR)) {
  510.             event.xcrossing.detail = NotifyAncestor;
  511.         } else {
  512.             event.xcrossing.detail = NotifyVirtual;
  513.         }
  514.         TkChangeEventWindow(&event, restrictWinPtr);
  515.         Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
  516.         }
  517.  
  518.     } else {
  519.         TkWindow *targetPtr;
  520.  
  521.         if ((lastMouseWinPtr == NULL)
  522.         || (lastMouseWinPtr->window == None)) {
  523.         targetPtr = winPtr;
  524.         } else {
  525.         targetPtr = lastMouseWinPtr;
  526.         }
  527.  
  528.         if (targetPtr && (targetPtr->window != None)) {
  529.         XEvent event;
  530.  
  531.         /*
  532.          * Generate appropriate Enter/Leave events.
  533.          */
  534.  
  535.         InitializeCrossingEvent(&event, targetPtr, x, y);
  536.  
  537.         TkInOutEvents(&event, lastMouseWinPtr, winPtr, LeaveNotify,
  538.             EnterNotify, TCL_QUEUE_TAIL);
  539.  
  540.         if (TkPositionInTree(winPtr, grabWinPtr) == TK_GRAB_IN_TREE) {
  541.             cursorWinPtr = winPtr;
  542.         } else {
  543.             cursorWinPtr = grabWinPtr;
  544.         }
  545.         crossed = 1;
  546.         }
  547.     }
  548.     lastMouseWinPtr = winPtr;
  549.     }
  550.  
  551.     /*
  552.      * Make sure the cursor reflects the current mouse position.
  553.      */
  554.  
  555.     if (restrictWinPtr) {
  556.     cursorWinPtr = restrictWinPtr;
  557.     } else if (grabWinPtr) {
  558.     cursorWinPtr = (TkPositionInTree(winPtr, grabWinPtr)
  559.         == TK_GRAB_IN_TREE) ? winPtr : grabWinPtr;
  560.     } else {
  561.     cursorWinPtr = winPtr;
  562.     }
  563.     TkWinUpdateCursor(cursorWinPtr);
  564.  
  565.     lastMouseWindow = hwnd;
  566.     lastMousePos.x = x;
  567.     lastMousePos.y = y;
  568.  
  569.     /*
  570.      * Ensure the mouse timer is set if we are still inside a Tk window.
  571.      */
  572.  
  573.     if (winPtr != NULL && !mouseTimerSet) {
  574.     mouseTimerSet = 1;
  575.     mouseTimer = Tcl_CreateTimerHandler(MOUSE_TIMER_INTERVAL,
  576.         MouseTimerProc, NULL);
  577.     }
  578.  
  579.     return crossed;
  580. }
  581.  
  582. /*
  583.  *----------------------------------------------------------------------
  584.  *
  585.  * MouseTimerProc --
  586.  *
  587.  *    Check the current mouse position and look for enter/leave 
  588.  *    events.
  589.  *
  590.  * Results:
  591.  *    None.
  592.  *
  593.  * Side effects:
  594.  *    May schedule a new timer and/or generate enter/leave events.
  595.  *
  596.  *----------------------------------------------------------------------
  597.  */
  598.  
  599. void
  600. MouseTimerProc(clientData)
  601.     ClientData clientData;
  602. {
  603.     POINT pos;
  604.     HWND hwnd;
  605.     TkWinDrawable *twdPtr;
  606.     TkWindow *winPtr;
  607.  
  608.     mouseTimerSet = 0;
  609.  
  610.     /*
  611.      * Get the current mouse position and window.  Don't do anything
  612.      * if the mouse hasn't moved since the last time we looked.
  613.      */
  614.  
  615.     GetCursorPos(&pos);
  616.     if (pos.x == lastMousePos.y && pos.y == lastMousePos.y) {
  617.     hwnd = lastMouseWindow;
  618.     } else {
  619.     hwnd = WindowFromPoint(pos);
  620.     }
  621.  
  622.     /*
  623.      * Check to see if the current window is managed by Tk.
  624.      */
  625.  
  626.     if (hwnd == lastMouseWindow) {
  627.     winPtr = lastMouseWinPtr;
  628.     } else {
  629.     twdPtr = TkWinGetDrawableFromHandle(hwnd);
  630.     if (twdPtr && (twdPtr->type == TWD_WINDOW)) {
  631.         winPtr = TkWinGetWinPtr(twdPtr);
  632.     } else {
  633.         winPtr = NULL;
  634.     }
  635.     }
  636.  
  637.     /*
  638.      * Generate enter/leave events.
  639.      */
  640.  
  641.     UpdateMousePosition(hwnd, winPtr, pos.x, pos.y);
  642. }
  643.  
  644. /*
  645.  *----------------------------------------------------------------------
  646.  *
  647.  * TkGetPointerCoords --
  648.  *
  649.  *    Fetch the position of the mouse pointer.
  650.  *
  651.  * Results:
  652.  *    *xPtr and *yPtr are filled in with the root coordinates
  653.  *    of the mouse pointer for the display.
  654.  *
  655.  * Side effects:
  656.  *    None.
  657.  *
  658.  *----------------------------------------------------------------------
  659.  */
  660.  
  661. void
  662. TkGetPointerCoords(tkwin, xPtr, yPtr)
  663.     Tk_Window tkwin;        /* Window that identifies screen on which
  664.                  * lookup is to be done. */
  665.     int *xPtr, *yPtr;        /* Store pointer coordinates here. */
  666. {
  667.     DWORD msgPos;
  668.     POINTS rootPoint;
  669.  
  670.     msgPos = GetMessagePos();
  671.     rootPoint = MAKEPOINTS(msgPos);
  672.     *xPtr = rootPoint.x;
  673.     *yPtr = rootPoint.y;
  674. }
  675.  
  676. /*
  677.  *----------------------------------------------------------------------
  678.  *
  679.  * XQueryPointer --
  680.  *
  681.  *    Check the current state of the mouse.  This is not a complete
  682.  *    implementation of this function.  It only computes the root
  683.  *    coordinates and the current mask.
  684.  *
  685.  * Results:
  686.  *    Sets root_x_return, root_y_return, and mask_return.  Returns
  687.  *    true on success.
  688.  *
  689.  * Side effects:
  690.  *    None.
  691.  *
  692.  *----------------------------------------------------------------------
  693.  */
  694.  
  695. Bool
  696. XQueryPointer(display, w, root_return, child_return, root_x_return,
  697.     root_y_return, win_x_return, win_y_return, mask_return)
  698.     Display* display;
  699.     Window w;
  700.     Window* root_return;
  701.     Window* child_return;
  702.     int* root_x_return;
  703.     int* root_y_return;
  704.     int* win_x_return;
  705.     int* win_y_return;
  706.     unsigned int* mask_return;
  707. {
  708.     TkGetPointerCoords(NULL, root_x_return, root_y_return);
  709.     *mask_return = TkWinGetModifierState(WM_MOUSEMOVE, 0, 0);    
  710.     return True;
  711. }
  712.  
  713. /*
  714.  *----------------------------------------------------------------------
  715.  *
  716.  * XGetInputFocus --
  717.  *
  718.  *    Retrieves the current keyboard focus window.
  719.  *
  720.  * Results:
  721.  *    Returns the current focus window.
  722.  *
  723.  * Side effects:
  724.  *    None.
  725.  *
  726.  *----------------------------------------------------------------------
  727.  */
  728.  
  729. void
  730. XGetInputFocus(display, focus_return, revert_to_return)
  731.     Display *display;
  732.     Window *focus_return;
  733.     int *revert_to_return;
  734. {
  735.     HWND hwnd = GetFocus();
  736.     TkWinDrawable *twdPtr = TkWinGetDrawableFromHandle(hwnd);
  737.  
  738.     /*
  739.      * The focus window may be a Tk window or a window manager decorative
  740.      * frame.
  741.      */
  742.  
  743.     if (twdPtr) {
  744.     *focus_return = Tk_WindowId(TkWinGetWinPtr(twdPtr));
  745.     } else {
  746.     *focus_return = NULL;
  747.     }
  748.     *revert_to_return = RevertToParent;
  749. }
  750.  
  751. /*
  752.  *----------------------------------------------------------------------
  753.  *
  754.  * XSetInputFocus --
  755.  *
  756.  *    Set the current focus window.
  757.  *
  758.  * Results:
  759.  *    None.
  760.  *
  761.  * Side effects:
  762.  *    Changes the keyboard focus and causes the selected window to
  763.  *    be activated.
  764.  *
  765.  *----------------------------------------------------------------------
  766.  */
  767.  
  768. void
  769. XSetInputFocus(display, focus, revert_to, time)
  770.     Display* display;
  771.     Window focus;
  772.     int revert_to;
  773.     Time time;
  774. {
  775.     HWND hwnd = TkWinGetHWND(focus);
  776.     SetFocus(hwnd);
  777. }
  778.  
  779. /*
  780.  *----------------------------------------------------------------------
  781.  *
  782.  * XDefineCursor --
  783.  *
  784.  *    This function is called to update the cursor on a window.
  785.  *    Since the mouse might be in the specified window, we need to
  786.  *    check the specified window against the current mouse position
  787.  *    and grab state.
  788.  *
  789.  * Results:
  790.  *    None.
  791.  *
  792.  * Side effects:
  793.  *    May update the cursor.
  794.  *
  795.  *----------------------------------------------------------------------
  796.  */
  797.  
  798. void
  799. XDefineCursor(display, w, cursor)
  800.     Display* display;
  801.     Window w;
  802.     Cursor cursor;
  803. {
  804.     TkWindow *winPtr = TkWinGetWinPtr(w);
  805.  
  806.     if (restrictWinPtr) {
  807.  
  808.     /*
  809.      * If there is a restrict window, then we only update the cursor
  810.      * if the restrict window is the window being modified.
  811.      */
  812.  
  813.     if (winPtr == restrictWinPtr) {
  814.         goto update;
  815.     }
  816.     } else if (grabWinPtr) {
  817.  
  818.     /*
  819.      * If a grab is in effect, then we only update the cursor if the mouse
  820.      * pointer is outside the grab tree and the specified window is the
  821.      * grab window, or the pointer is inside the grab tree and the
  822.      * specified window is also the pointer window.
  823.      */
  824.  
  825.     if (TkPositionInTree(lastMouseWinPtr, grabWinPtr) == TK_GRAB_IN_TREE) {
  826.         if (winPtr == lastMouseWinPtr) {
  827.         goto update;
  828.         }
  829.     } else if (winPtr == grabWinPtr) {
  830.         goto update;
  831.     }
  832.     } else {
  833.  
  834.     /*
  835.      * Otherwise, we only update the cursor if the specified window
  836.      * contains the mouse pointer.
  837.      */
  838.  
  839.     if (winPtr == lastMouseWinPtr) {
  840.         goto update;
  841.     }
  842.     }
  843.     return;
  844.  
  845. update:
  846.     TkWinUpdateCursor(winPtr);
  847. }
  848.  
  849.